﻿// 示例代码 3-1
// 智能指针的部分模拟实现
#include <iostream>
#include <atomic>
#include <cassert>
#include <functional>
using namespace std;

struct Date
{
	Date(int year = 1970, int month = 1, int day = 1)
		: _year(year)
		, _month(month)
		, _day(day)
	{}

	~Date()
	{
		cout << "~Date" << endl;
		_year = 0;
		_month = 0;
		_day = 0;
	}

	int _year;
	int _month;
	int _day;
};

namespace yyp
{
	template <class T>
	class auto_ptr
	{
	public:
		explicit auto_ptr(T* ptr = nullptr)
			: _ptr(ptr)
		{}

		// 管理权转移
		auto_ptr(auto_ptr& ap)
			: _ptr(ap._ptr)
		{
			ap._ptr = nullptr;
		}

		auto_ptr& operator=(auto_ptr& ap)
		{
			if (this != &ap)
			{
				if (_ptr)
					delete _ptr;	// 释放当前对象中资源

				_ptr = ap._ptr;		// 转移资源
				ap._ptr = nullptr;
			}

			return *this;
		}

		T* get() const
		{
			return _ptr;
		}

		// 像指针⼀样使⽤
		T& operator*() const
		{
			if (!_ptr)
				assert(false);

			return *_ptr;
		}

		T* operator->() const
		{
			if (!_ptr)
				assert(false);

			return _ptr;
		}

		~auto_ptr()
		{
			if (_ptr)
			{
				cout << "auto_ptr delete: " << _ptr << endl;
				delete _ptr;
				_ptr = nullptr;
			}
		}

	private:
		T* _ptr;
	};

	template <class T>
	class unique_ptr
	{
	public:
		explicit unique_ptr(T* ptr = nullptr)
			: _ptr(ptr)
		{}

		unique_ptr(const unique_ptr& up) = delete;
		unique_ptr operator=(const unique_ptr& up) = delete;

		unique_ptr(unique_ptr&& up) noexcept
			: _ptr(up._ptr)
		{
			up._ptr = nullptr;
		}

		unique_ptr& operator=(unique_ptr&& up)
		{
			if (_ptr)
				delete _ptr;

			_ptr = up._ptr;
			up._ptr = nullptr;

			return *this;
		}

		T* get() const
		{
			return _ptr;
		}

		// 像指针⼀样使⽤
		T& operator*() const
		{
			if (!_ptr)
				assert(false);

			return *_ptr;
		}

		T* operator->() const
		{
			if (!_ptr)
				assert(false);

			return _ptr;
		}

		~unique_ptr()
		{
			if (_ptr)
			{
				cout << "unique_ptr delete: " << _ptr << endl;
				delete _ptr;
				_ptr = nullptr;
			}
		}

	private:
		T* _ptr;
	};

	template <class T>
	class shared_ptr
	{
	public:
		explicit shared_ptr(T* ptr = nullptr)
			: _ptr(ptr)
			, _pcount(new atomic<int>(1))
		{}

		// 1、类模板与成员函数模板的同名模板参数（如均用T）会因作用域嵌套发生名称遮蔽，编译器会将其识别为两个完全独立的类型参数
		// 建议使用不同命名，显式指明这两个模板参数可以是不同类型
		// 实例化的模板函数中，二者的实际类型要么相同，要么是（类模板）基类和（成员函数模板）派生类的关系，都可以执行_ptr(ptr)的赋值操作
		// 2、可以将模板参数简化为一个。此时可以直接使用类模板的T参数 template <class D>
		//template <class T, class D>
		template <class U, class D>
		shared_ptr(U* ptr, D del)
			: _ptr(ptr)
			, _pcount(new atomic<int>(1))
			, _del(del)
		{}

		shared_ptr(const shared_ptr& sp)
			: _ptr(sp._ptr)
			, _pcount(sp._pcount)
			, _del(sp._del)
		{
			++(*_pcount);
		}

		shared_ptr(shared_ptr&& sp)
		{
			_ptr = sp._ptr;
			_pcount = sp._pcount;
			_del = sp._del;

			sp._ptr = nullptr;
			sp._pcount = nullptr;
		}

		shared_ptr& operator=(const shared_ptr& sp)
		{
			//if (this != &sp)
			if (_ptr != sp._ptr)
			{
				release();

				_ptr = sp._ptr;
				_pcount = sp._pcount;
				++(*_pcount);
				_del = sp._del;
			}

			return *this;
		}

		shared_ptr& operator=(shared_ptr&& sp)
		{
			if (_ptr != sp._ptr)
			{
				release();

				_ptr = sp._ptr;
				_pcount = sp._pcount;
				++(*_pcount);
				_del = move(sp._del); // 移动删除器（function支持移动，更高效）
			}

			return *this;
		}

		void release()
		{
			if (_pcount && 0 == --(*_pcount))
			{
				// 最后⼀个管理资源的对象析构时，释放其管理的资源
				_del(_ptr);
				delete _pcount;
				_ptr = nullptr;
				_pcount = nullptr;
			}
		}

		T& operator*() const
		{
			if (!_ptr)
				assert(false);

			return *_ptr;
		}

		T* operator->() const
		{
			if (!_ptr)
				assert(false);

			return _ptr;
		}

		int use_count() const
		{
			// 返回0仅表示不持有资源的空实例
			return _pcount ? _pcount->load() : 0;

			//return *_pcount;			// atomic<int> 到 int 的转换
			//return _pcount->load();	// 返回存储的int值
		}

		T* get() const
		{
			return _ptr;
		}

		~shared_ptr()
		{
			cout << "shared_ptr delete: ";
			if (!_ptr)
			{
				cout << "空对象";
			}
			else
			{
				//cout << "引用计数 " << (_pcount ? *_pcount : 0);	// err
				cout << "引用计数 " << (_pcount ? _pcount->load() : 0);
				if (_pcount && 1 == _pcount->load())
					cout << " ，释放管理的资源 " << _ptr;
			}
			cout << endl;

			release();
		}

	private:
		T* _ptr;
		//int* _pcount;
		atomic<int>* _pcount;	// 原子类型，线程安全

		function<void(T*)> _del = [](T* ptr) {
			delete ptr;
			ptr = nullptr;
		};
	};

	// 这里的shared_ptr和weak_ptr都是以最简洁的⽅式实现只能满⾜基本的功能
	// weak_ptr的lock等功能这里⽆法实现，想要实现就要同时修改shared_ptr和weak_ptr
	// 把引⽤计数取出设计为⼀个单独的类，shared_ptr和weak_ptr都要存储指向这个类的对象
	// 有兴趣可以翻翻源代码
	template <class T>
	class weak_ptr
	{
	public:
		weak_ptr()
		{}

		weak_ptr(const shared_ptr<T>& sp)
			: _ptr(sp.get())
		{}

		weak_ptr& operator=(const shared_ptr<T>& sp)
		{
			_ptr = sp.get();

			return *this;
		}

	private:
		T* _ptr = nullptr;
	};

	void Test4()
	{
		auto_ptr<Date> ap1(new Date);
		auto_ptr<Date> ap2(ap1);		// ap1被悬空

		//ap1->_year;					// 空指针访问，ap1已悬空

		unique_ptr<Date> up1(new Date);
		//unique_ptr<Date> up2(up1);	// 不支持拷贝
		unique_ptr<Date> up3(move(up1));// 支持移动

		shared_ptr<Date> sp1(new Date);
		shared_ptr<Date> sp2(sp1);		// 支持拷贝
		shared_ptr<Date> sp3(sp2);		// sp1、sp2、sp3管理同一个资源

		cout << "auto_ptr  : " << ap1.get() << "\t" << ap2.get() << endl;
		cout << "unique_ptr: " << up1.get() << "\t" << up3.get() << endl;
		cout << "shared_ptr: " << sp1.get() << "\t" << sp2.get() << "\t" << sp3.get() << endl << endl;

		cout << sp1.use_count() << "\t" << sp2.use_count() << "\t" << sp3.use_count() << endl << endl;

		cout << sp1->_year << "\t" << sp2->_year << "\t" << sp3->_year << endl;
		++sp3->_year;
		cout << sp1->_year << "\t" << sp2->_year << "\t" << sp3->_year << endl << endl;

		shared_ptr<Date> sp4(move(sp1));// ⽀持移动
		cout << sp4.use_count() << endl << endl;
	}

}

void Test5()
{
	atomic<int> a = 10;

	cout << a << endl;
	cout << a.load() << endl;
}

namespace yyp
{
	template <class T>
	struct ListNode
	{
		T _data;
		ListNode* _next;
		ListNode* _prev;
	};

	template <class T>
	using Node = ListNode<T>;

	struct list_head 
	{
		struct list_head* next, * prev;
	};

	struct task_struct
	{
		int x;
		int y;
		int z;
		list_head links;
		// 其它...
	};
}

#include <stddef.h>
void Test6()
{
	int arr[] = { 0, 1, 2, 3, 4, 5 };
	int* p1 = &arr[0], * p2 = &arr[5];

	cout << (p2 - p1) << endl;
	printf("%p %p\n", p1, p2);
	cout << (p1 + 2) << " " << *(p1 + 2) << endl;
	cout << (p2 - 2) << " " << *(p2 - 2) << endl;

	struct A
	{
		int a;
	};

	offsetof(A, a);
}

int main()
{
#if 0
	yyp::Test4();
	Test5();
#endif
	Test6();

	return 0;
}
